package pl.edu.agh.mguesser.metadata;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import org.jaudiotagger.audio.AudioFile;
import org.jaudiotagger.audio.AudioFileIO;
import org.jaudiotagger.audio.exceptions.CannotReadException;
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
import org.jaudiotagger.audio.mp3.MP3AudioHeader;
import org.jaudiotagger.tag.FieldKey;
import org.jaudiotagger.tag.Tag;
import org.jaudiotagger.tag.TagException;
import org.springframework.stereotype.Service;

/**
 * @author keiran
 */
@Service
public class MetadataProviderImpl implements MetadataProvider {

    private AudioFileFactory audioFileFactory = new SimpleAudioFileFactory();
    
    @Override
    public Metadata getMetadataFor(Path path) throws MetadataProviderException {
        File file = path.toFile();
        
        if(!file.exists()) {
            Exception cause = new IllegalArgumentException("no such file");
            throw new MetadataProviderException(cause);
        }
        
        AudioFile audioFile = audioFileFactory.createAudioFile(file);
        Tag tag = audioFile.getTag();
        MP3AudioHeader audioHeader;
        
        try {
            audioHeader = (MP3AudioHeader) audioFile.getAudioHeader();
            
        } catch(ClassCastException ex) {
            throw new MetadataProviderException(ex);
            
        }
        
        Metadata result = new Metadata(path);
        result.setArtist(tag.getFirst(FieldKey.ARTIST));
        result.setAlbum(tag.getFirst(FieldKey.ALBUM));
        result.setTitle(tag.getFirst(FieldKey.TITLE));
        result.setFrameCount(audioHeader.getNumberOfFrames());
        result.setTrackLength(audioHeader.getTrackLength());
        
        return result;
    }

    void setAudioFileFactory(AudioFileFactory audioFileFactory) {
        this.audioFileFactory = audioFileFactory;
    }
    
    static interface AudioFileFactory {
        AudioFile createAudioFile(File file) throws MetadataProviderException;
    }
    
    private static class SimpleAudioFileFactory implements AudioFileFactory {
        
        @Override
        public AudioFile createAudioFile(File file) throws MetadataProviderException {
            try {
                return AudioFileIO.read(file);
                
            } catch (CannotReadException | IOException | TagException 
                    | ReadOnlyFileException | InvalidAudioFrameException ex) {
                throw new MetadataProviderException(ex);
                
            }
        }
        
    }

}
